home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Overload Trio 2
/
Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO
/
dir39
/
550reset.zip
/
550RESET.C
next >
Wrap
C/C++ Source or Header
|
1994-08-06
|
4KB
|
145 lines
/*
This program clears the 16550A's FIFO to prevent system hangs
when "Super I/O" cards with SMC665 or SMC666 chips are used with
communications programs that enable the 16550A UART. Just run this
program before you run your favorite communications program and you
should *not* experience further system hangs. NOTE: If you have an
external device connect it and turn it on BEFORE you run this program.
The specific problem is that if you output a 0x7 to the FIFO control
register of these chips while there is data in the FIFO the chip will
go into a state where the Receive Ready flag (bit 0 in the LSR)
remains high NO MATTER HOW MANY TIMES YOU READ THE RECEIVER BUFFER
REGISTER. If your communication program is unfortunate enough to enable
interrupts while the UART is in this condition your system will lockup,
and require a hardware reset or power cycle to restore operation.
Needless to say this is inconvenient!
I discovered this problem when I upgraded my "SUPER I/O card" to a
"SIDE jr L" vlb card. While the features are great I immediately ran into
problem with EVERY program I have that uses serial I/O. I found that I
could only execute Windows programs that used serial I/O once, the
whole system locked up the second time I ran the program. This occurred
with several different Windows programs. Searching the Microsoft Knowledge
base yielded the answer... an updated SERIAL.386 driver (search for
WG1001 for the new driver). Unfortunately the new Windows driver did
nothing for DOS programs I use regularly such as Qmodem and Telix, that is
why I wrote this program. The Microsoft writeup provided enough
information on the problem for this program to be written.
Comments are welcome:
Skip Hansen WB6YMH.
internet: wb6ymh@amsat.org
BBS: (310) 541-2503
Packet: WB6YMH@WB6YMH.#SOCAL.CA.USA
If you find this program of value I am pleased, send no cash!
*/
enum UART_TYPE{
UNKNOWN,
UART_TYPE_8250,
UART_TYPE_16450,
UART_TYPE_16550,
UART_TYPE_16550A
};
#define RBR 0
#define THR 0
#define IER 1
#define FCR 2
#define IIR 2
#define LCR 3
#define MCR 4
#define LSR 5
#define MSR 6
#define SCR 7
#define FIFO_ENABLED_6 0x40
#define FIFO_ENABLED_7 0x80
#define FIFO_ENABLE 1
void reset(int port)
{
int i;
outp(port+FCR,1); // enable FIFO
if( (inp(port+IIR) & 0xc0) != 0xc0){
printf("Port 0x%0x does not appear to be an 16550 UART.\n",port);
return;
}
outp(port+FCR,0); // disable FIFO
i = 0;
while(i++ < 16 && (inp(port+LSR) & 1)){
inp(port+RBR);
}
if(i == 16){
printf("Unable to clear FIFO on UART at port 0x%0x after 16 reads!\n",port);
}
return;
}
enum UART_TYPE id_uart(int port)
{
char temp;
// first check the scratch register
temp = inp(port+SCR);
outp(port+SCR,0x55);
if(inp(port+SCR) != 0x55){
printf("Uart at port 0x%0x is a 8250.\n",port);
return UART_TYPE_8250;
}
outp(port+SCR,0xaa);
if(inp(port+SCR) != 0xaa){
printf("UART at port 0x%0x is a 8250.\n",port);
return UART_TYPE_8250;
}
outp(port+SCR,temp); // restore original value (an case anyone cares!)
// we have at least a 16450.
outp(port+FCR,0); // disable the FIFO
if((inp(port+IIR) & FIFO_ENABLED_6) != 0 || (inp(port+IIR) & FIFO_ENABLED_6) != 0){
printf("Unknown UART at port 0x%0x.\n",port);
printf("(Bits 6 and 7 of the IIR are not ZERO with the FIFO disabled.\n");
return UNKNOWN;
}
outp(port+FCR,FIFO_ENABLE); // enable the FIFO
if((inp(port+IIR) & FIFO_ENABLED_6) != FIFO_ENABLED_6) {
printf("UART at port 0x%0x is a 16450.\n",port);
return UART_TYPE_16450;
}
if((inp(port+IIR) & FIFO_ENABLED_7) != FIFO_ENABLED_7) {
printf("UART at port 0x%0x is a 16550.\n",port);
printf("(NOT a 16550A, do not use the FIFO function, it's BROKEN!)\n");
return UART_TYPE_16550;
}
printf("UART at port 0x%0x is a 16550A.\n",port);
return UART_TYPE_16550A;
}
main()
{
if(id_uart(0x2f8) == UART_TYPE_16550A){
reset(0x2f8);
}
if(id_uart(0x3f8) == UART_TYPE_16550A){
reset(0x3f8);
}
}